/*
 * Copyright (C) 2015-2020, Wazuh Inc.
 *
 * This program is free software; you can redistribute it
 * and/or modify it under the terms of the GNU General Public
 * License (version 2) as published by the FSF - Free Software
 * Foundation.
 */

#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>
#include <stdio.h>

#include "../../wazuh_modules/wmodules.h"
#include "../../headers/shared.h"
#include "mocks_wm_vuln_detector.h"

#define REPORT_CVE_VULDET_POS 0
#define REPORT_CVE_REPORT_POS 1

int order(int c);
static int (*comparator) (const char *, const char *, int);
int pkg_version_compare(const struct pkg_version *a, const struct pkg_version *b);
bool pkg_version_relate(const struct pkg_version *a, enum pkg_relation rel, const struct pkg_version *b, version_type vertype);
int deb_verrevcmp(const char *a, const char *b, __attribute__((unused)) int revision);
int nvd_verrevcmp(const char *a, const char *b, int revision);

/* setup/teardown */

static int setup_versions(void **state) {
    struct pkg_version *version_a;
    struct pkg_version *version_b;

    os_calloc(1, sizeof(struct pkg_version), version_a);
    os_calloc(1, sizeof(struct pkg_version), version_b);

    if(!version_a || !version_b) {
        return -1;
    }

    state[0] = version_a;
    state[1] = version_b;

    return 0;
}

static int teardown_versions(void **state) {
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    if(version_a) {
        free(version_a);
    }

    if(version_b) {
        free(version_b);
    }

    return 0;
}

/* tests */

/* order */

void test_order_digit(void **state)
{
    int ret = order('1');
    assert_int_equal(ret, 0);
}

void test_order_alpha(void **state)
{
    int ret = order('a');
    assert_int_equal(ret, 'a');
}

void test_order_tilde(void **state)
{
    int ret = order('~');
    assert_int_equal(ret, -1);
}

void test_order_other(void **state)
{
    int ret = order('.');
    assert_int_equal(ret, '.' + 256);
}

void test_order_zero(void **state)
{
    int ret = order(0);
    assert_int_equal(ret, 0);
}

/* pkg_version_relate */

void test_pkg_version_relate_epoch_NONE(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 1;
    version_a->version = "";
    version_a->revision = "";
    version_b->epoch = 0;
    version_b->version = "";
    version_b->revision = "";

    int ret = pkg_version_relate(version_a, PKG_RELATION_GT, version_b, VER_TYPE_NONE);
    assert_int_equal(ret, 1);
}

void test_pkg_version_relate_epoch_VER_TYPE_unknown(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 1;
    version_a->version = "";
    version_a->revision = "";
    version_b->epoch = 0;
    version_b->version = "";
    version_b->revision = "";

    expect_string(__wrap__mterror, tag, "wazuh-modulesd:vulnerability-detector");
    expect_string(__wrap__mterror, formatted_msg, "unknown version_type 4");

    int ret = pkg_version_relate(version_a, PKG_RELATION_GT, version_b, 4);
    assert_int_equal(ret, 0);
}

void test_pkg_version_relate_epoch_RELATION_unknown(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 1;
    version_a->version = "";
    version_a->revision = "";
    version_b->epoch = 0;
    version_b->version = "";
    version_b->revision = "";

    expect_string(__wrap__mterror, tag, "wazuh-modulesd:vulnerability-detector");
    expect_string(__wrap__mterror, formatted_msg, "unknown pkg_relation 6");

    int ret = pkg_version_relate(version_a, 6, version_b, VER_TYPE_DEB);
    assert_int_equal(ret, 0);
}

void test_pkg_version_relate_epoch_GT(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 1;
    version_a->version = "";
    version_a->revision = "";
    version_b->epoch = 0;
    version_b->version = "";
    version_b->revision = "";

    int ret = pkg_version_relate(version_a, PKG_RELATION_GT, version_b, VER_TYPE_DEB);
    assert_int_equal(ret, 1);
}

void test_pkg_version_relate_epoch_GE(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 1;
    version_a->version = "";
    version_a->revision = "";
    version_b->epoch = 0;
    version_b->version = "";
    version_b->revision = "";

    int ret = pkg_version_relate(version_a, PKG_RELATION_GE, version_b, VER_TYPE_DEB);
    assert_int_equal(ret, 1);
}

void test_pkg_version_relate_epoch_EQ(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 1;
    version_a->version = "";
    version_a->revision = "";
    version_b->epoch = 0;
    version_b->version = "";
    version_b->revision = "";

    int ret = pkg_version_relate(version_a, PKG_RELATION_EQ, version_b, VER_TYPE_DEB);
    assert_int_equal(ret, 0);
}

void test_pkg_version_relate_epoch_LE(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "";
    version_a->revision = "";
    version_b->epoch = 1;
    version_b->version = "";
    version_b->revision = "";

    int ret = pkg_version_relate(version_a, PKG_RELATION_LE, version_b, VER_TYPE_DEB);
    assert_int_equal(ret, 1);
}

void test_pkg_version_relate_epoch_LT(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "";
    version_a->revision = "";
    version_b->epoch = 1;
    version_b->version = "";
    version_b->revision = "";

    int ret = pkg_version_relate(version_a, PKG_RELATION_LT, version_b, VER_TYPE_DEB);
    assert_int_equal(ret, 1);
}

void test_pkg_version_relate_epoch_negative_nvd(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = -1;
    version_a->version = "1";
    version_a->revision = "";
    version_b->epoch = -1;
    version_b->version = "2";
    version_b->revision = "";

    int ret = pkg_version_relate(version_a, PKG_RELATION_EQ, version_b, VER_TYPE_NVD);
    assert_int_equal(ret, 0);
}

void test_pkg_version_relate_version_deb_GT(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "5.3.0.45";
    version_a->revision = "";
    version_b->epoch = 0;
    version_b->version = "4.18.1";
    version_b->revision = "";

    int ret = pkg_version_relate(version_a, PKG_RELATION_GT, version_b, VER_TYPE_DEB);
    assert_int_equal(ret, 1);
}

void test_pkg_version_relate_version_deb_GT_zero_ending(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "5.3.0";
    version_a->revision = "";
    version_b->epoch = 0;
    version_b->version = "5.3";
    version_b->revision = "";

    int ret = pkg_version_relate(version_a, PKG_RELATION_GT, version_b, VER_TYPE_DEB);
    assert_int_equal(ret, 1);
}

void test_pkg_version_relate_version_deb_GE(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "5.3.0.45";
    version_a->revision = "";
    version_b->epoch = 0;
    version_b->version = "4.18.1";
    version_b->revision = "";

    int ret = pkg_version_relate(version_a, PKG_RELATION_GE, version_b, VER_TYPE_DEB);
    assert_int_equal(ret, 1);
}

void test_pkg_version_relate_version_deb_EQ(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "5.3.0.45";
    version_a->revision = "";
    version_b->epoch = 0;
    version_b->version = "4.18.1";
    version_b->revision = "";

    int ret = pkg_version_relate(version_a, PKG_RELATION_EQ, version_b, VER_TYPE_DEB);
    assert_int_equal(ret, 0);
}

void test_pkg_version_relate_version_deb_LE(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "5.3.0.45";
    version_a->revision = "";
    version_b->epoch = 0;
    version_b->version = "4.18.1";
    version_b->revision = "";

    int ret = pkg_version_relate(version_a, PKG_RELATION_LE, version_b, VER_TYPE_DEB);
    assert_int_equal(ret, 0);
}

void test_pkg_version_relate_version_deb_LT(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "5.3.0.45";
    version_a->revision = "";
    version_b->epoch = 0;
    version_b->version = "4.18.1";
    version_b->revision = "";

    int ret = pkg_version_relate(version_a, PKG_RELATION_LT, version_b, VER_TYPE_DEB);
    assert_int_equal(ret, 0);
}

void test_pkg_version_relate_version_rpm_GT(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "5.3.0.45";
    version_a->revision = "";
    version_b->epoch = 0;
    version_b->version = "4.18.1";
    version_b->revision = "";

    int ret = pkg_version_relate(version_a, PKG_RELATION_GT, version_b, VER_TYPE_RPM);
    assert_int_equal(ret, 1);
}

void test_pkg_version_relate_version_rpm_GT_zero_ending(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "5.3.0";
    version_a->revision = "";
    version_b->epoch = 0;
    version_b->version = "5.3";
    version_b->revision = "";

    int ret = pkg_version_relate(version_a, PKG_RELATION_GT, version_b, VER_TYPE_RPM);
    assert_int_equal(ret, 1);
}

void test_pkg_version_relate_version_rpm_GE(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "5.3.0.45";
    version_a->revision = "";
    version_b->epoch = 0;
    version_b->version = "4.18.1";
    version_b->revision = "";

    int ret = pkg_version_relate(version_a, PKG_RELATION_GE, version_b, VER_TYPE_RPM);
    assert_int_equal(ret, 1);
}

void test_pkg_version_relate_version_rpm_EQ(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "5.3.0.45";
    version_a->revision = "";
    version_b->epoch = 0;
    version_b->version = "4.18.1";
    version_b->revision = "";

    int ret = pkg_version_relate(version_a, PKG_RELATION_EQ, version_b, VER_TYPE_RPM);
    assert_int_equal(ret, 0);
}

void test_pkg_version_relate_version_rpm_LE(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "5.3.0.45";
    version_a->revision = "";
    version_b->epoch = 0;
    version_b->version = "4.18.1";
    version_b->revision = "";

    int ret = pkg_version_relate(version_a, PKG_RELATION_LE, version_b, VER_TYPE_RPM);
    assert_int_equal(ret, 0);
}

void test_pkg_version_relate_version_nvd_GE(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "t32.10";
    version_a->revision = "";
    version_b->epoch = 0;
    version_b->version = "t5.10";
    version_b->revision = "";

    int ret = pkg_version_relate(version_a, PKG_RELATION_GE, version_b, VER_TYPE_NVD);
    assert_int_equal(ret, 1);
}

void test_pkg_version_relate_version_nvd_LE(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "6.3.0";
    version_a->revision = "";
    version_b->epoch = 0;
    version_b->version = "6.3.0r1";
    version_b->revision = "";

    int ret = pkg_version_relate(version_a, PKG_RELATION_LE, version_b, VER_TYPE_NVD);
    assert_int_equal(ret, 1);
}

void test_pkg_version_relate_version_rpm_LT(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "5.3.0.45";
    version_a->revision = "";
    version_b->epoch = 0;
    version_b->version = "4.18.1";
    version_b->revision = "";

    int ret = pkg_version_relate(version_a, PKG_RELATION_LT, version_b, VER_TYPE_RPM);
    assert_int_equal(ret, 0);
}

void test_pkg_version_relate_revision_deb_GT(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "5.3.0.45";
    version_a->revision = "2+2ubuntu1.2";
    version_b->epoch = 0;
    version_b->version = "5.3.0.45";
    version_b->revision = "2+2ubuntu1.1";

    int ret = pkg_version_relate(version_a, PKG_RELATION_GT, version_b, VER_TYPE_DEB);
    assert_int_equal(ret, 1);
}

void test_pkg_version_relate_revision_deb_GE(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "5.3.0.45";
    version_a->revision = "2+2ubuntu1.2";
    version_b->epoch = 0;
    version_b->version = "5.3.0.45";
    version_b->revision = "2+2ubuntu1.1";

    int ret = pkg_version_relate(version_a, PKG_RELATION_GE, version_b, VER_TYPE_DEB);
    assert_int_equal(ret, 1);
}

void test_pkg_version_relate_revision_deb_EQ(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "5.3.0.45";
    version_a->revision = "2+2ubuntu1.2";
    version_b->epoch = 0;
    version_b->version = "5.3.0.45";
    version_b->revision = "2+2ubuntu1.1";

    int ret = pkg_version_relate(version_a, PKG_RELATION_EQ, version_b, VER_TYPE_DEB);
    assert_int_equal(ret, 0);
}

void test_pkg_version_relate_revision_deb_LE(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "5.3.0.45";
    version_a->revision = "2+2ubuntu1.2";
    version_b->epoch = 0;
    version_b->version = "5.3.0.45";
    version_b->revision = "2+2ubuntu1.1";

    int ret = pkg_version_relate(version_a, PKG_RELATION_LE, version_b, VER_TYPE_DEB);
    assert_int_equal(ret, 0);
}

void test_pkg_version_relate_revision_deb_LT(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "5.3.0.45";
    version_a->revision = "2+2ubuntu1.1";
    version_b->epoch = 0;
    version_b->version = "5.3.0.45";
    version_b->revision = "2+22";

    int ret = pkg_version_relate(version_a, PKG_RELATION_LT, version_b, VER_TYPE_DEB);
    assert_int_equal(ret, 1);
}

void test_pkg_version_relate_revision_rpm_GT(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "5.3.0.45";
    version_a->revision = "12.9";
    version_b->epoch = 0;
    version_b->version = "5.3.0.45";
    version_b->revision = "2.el8";

    int ret = pkg_version_relate(version_a, PKG_RELATION_GT, version_b, VER_TYPE_RPM);
    assert_int_equal(ret, 1);
}

void test_pkg_version_relate_revision_rpm_GE(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "5.3.0.45";
    version_a->revision = "12.9";
    version_b->epoch = 0;
    version_b->version = "5.3.0.45";
    version_b->revision = "2.el8";

    int ret = pkg_version_relate(version_a, PKG_RELATION_GE, version_b, VER_TYPE_RPM);
    assert_int_equal(ret, 1);
}

void test_pkg_version_relate_revision_rpm_EQ(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "5.3.0.45";
    version_a->revision = "12.9";
    version_b->epoch = 0;
    version_b->version = "5.3.0.45";
    version_b->revision = "2.el8";

    int ret = pkg_version_relate(version_a, PKG_RELATION_EQ, version_b, VER_TYPE_RPM);
    assert_int_equal(ret, 0);
}

void test_pkg_version_relate_revision_rpm_LE(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "5.3.0.45";
    version_a->revision = "12.9";
    version_b->epoch = 0;
    version_b->version = "5.3.0.45";
    version_b->revision = "2.el8";

    int ret = pkg_version_relate(version_a, PKG_RELATION_LE, version_b, VER_TYPE_RPM);
    assert_int_equal(ret, 0);
}

void test_pkg_version_relate_revision_rpm_LT(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "5.3.0.45";
    version_a->revision = "2.el8";
    version_b->epoch = 0;
    version_b->version = "5.3.0.45";
    version_b->revision = "2.9";

    int ret = pkg_version_relate(version_a, PKG_RELATION_LT, version_b, VER_TYPE_RPM);
    assert_int_equal(ret, 1);
}

void test_pkg_version_relate_revision_rpm_tilde(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "5.3.0.45";
    version_a->revision = "12.9~145";
    version_b->epoch = 0;
    version_b->version = "5.3.0.45";
    version_b->revision = "12.9~178";

    int ret = pkg_version_relate(version_a, PKG_RELATION_LT, version_b, VER_TYPE_RPM);
    assert_int_equal(ret, 1);
}

void test_pkg_version_relate_revision_rpm_caret_separator(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "5.3.0.45";
    version_a->revision = "12.9^18";
    version_b->epoch = 0;
    version_b->version = "5.3.0.45";
    version_b->revision = "12.9^178";

    int ret = pkg_version_relate(version_a, PKG_RELATION_LT, version_b, VER_TYPE_RPM);
    assert_int_equal(ret, 1);
}

void test_pkg_version_relate_revision_deb_null(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "1";
    version_a->revision = NULL;
    version_b->epoch = 0;
    version_b->version = "1";
    version_b->revision = NULL;

    int ret = pkg_version_relate(version_a, PKG_RELATION_EQ, version_b, VER_TYPE_DEB);
    assert_int_equal(ret, 1);
}

void test_pkg_version_relate_revision_nvd_null(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_a->version = "1";
    version_a->revision = NULL;
    version_b->epoch = 0;
    version_b->version = "1";
    version_b->revision = NULL;

    int ret = pkg_version_relate(version_a, PKG_RELATION_EQ, version_b, VER_TYPE_NVD);
    assert_int_equal(ret, 1);
}

/* pkg_version_compare */

void test_pkg_version_compare_epoch_negative(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = -1;
    version_b->epoch = -1;

    version_a->version = NULL;
    version_b->version = NULL;

    version_b->revision = NULL;
    version_b->revision = NULL;

    int ret = pkg_version_compare(version_a, version_b);
    assert_int_equal(ret, 0);
}

void test_pkg_version_compare_epoch_negative_a_greater(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = -1;
    version_b->epoch = -1;

    version_a->version = "1.0.0";
    version_b->version = "0.0.0";

    version_b->revision = NULL;
    version_b->revision = NULL;

    int ret = pkg_version_compare(version_a, version_b);
    assert_int_equal(ret, 1);
}

void test_pkg_version_compare_epoch_negative_b_greater(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = -1;
    version_b->epoch = -1;

    version_a->version = "0.0.0";
    version_b->version = "1.0.0";

    version_b->revision = NULL;
    version_b->revision = NULL;

    int ret = pkg_version_compare(version_a, version_b);
    assert_int_equal(ret, -1);
}

void test_pkg_version_compare_epoch_same_version(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = -1;
    version_b->epoch = -1;

    version_a->version = "1.0.0";
    version_b->version = "1.0.0";

    version_b->revision = NULL;
    version_b->revision = NULL;

    int ret = pkg_version_compare(version_a, version_b);
    assert_int_equal(ret, 0);
}

void test_pkg_version_compare_a_greater_than_b(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 1;
    version_b->epoch = 0;

    version_a->version = NULL;
    version_b->version = NULL;

    version_b->revision = NULL;
    version_b->revision = NULL;

    int ret = pkg_version_compare(version_a, version_b);
    assert_int_equal(ret, 1);
}

void test_pkg_version_compare_a_less_than_b(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_b->epoch = 1;

    version_a->version = NULL;
    version_b->version = NULL;

    version_b->revision = NULL;
    version_b->revision = NULL;

    int ret = pkg_version_compare(version_a, version_b);
    assert_int_equal(ret, -1);
}

void test_pkg_version_compare_version(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 1;
    version_b->epoch = 1;

    version_a->version = "1.0";
    version_b->version = "1.2";

    version_b->revision = NULL;
    version_b->revision = NULL;

    int ret = pkg_version_compare(version_a, version_b);
    assert_int_equal(ret, -1);
}


void test_pkg_version_compare_revision(void **state)
{
    struct pkg_version *version_a = state[0];
    struct pkg_version *version_b = state[1];

    version_a->epoch = 0;
    version_b->epoch = 0;

    version_a->version = NULL;
    version_b->version = NULL;

    version_b->revision = "1.0";
    version_b->revision = "1.0";

    int ret = pkg_version_compare(version_a, version_b);
    assert_int_equal(ret, 0);
}

/* deb_verrevcmp */
void test_deb_verrevcmp_version_a_NULL(void **state)
{
    char *version_a = NULL;
    char *version_b = NULL;
    int revision = 0;

    int ret = deb_verrevcmp(version_a, version_b, revision);
    assert_int_equal(ret, 0);
}

void test_deb_verrevcmp_version_b_NULL(void **state)
{
    char *version_a = NULL;
    char *version_b = NULL;
    int revision = 0;

    int ret = deb_verrevcmp(version_a, version_b, revision);
    assert_int_equal(ret, 0);
}

void test_deb_verrevcmp_same_version(void **state)
{
    char *version_a = "0";
    char *version_b = "0";
    int revision = 0;

    int ret = deb_verrevcmp(version_a, version_b, revision);
    assert_int_equal(ret, 0);
}

void test_deb_verrevcmp_text_version(void **state)
{
    char *version_a = "test";
    char *version_b = "test";
    int revision = 0;

    int ret = deb_verrevcmp(version_a, version_b, revision);
    assert_int_equal(ret, 0);
}

void test_deb_verrevcmp_version_a_newer(void **state)
{
    char *version_a = "0";
    char *version_b = "1";
    int revision = 0;

    int ret = deb_verrevcmp(version_a, version_b, revision);
    assert_int_equal(ret, -1);
}

void test_deb_verrevcmp_version_b_newer(void **state)
{
    char *version_a = "1";
    char *version_b = "0";
    int revision = 0;

    int ret = deb_verrevcmp(version_a, version_b, revision);
    assert_int_equal(ret, 1);
}

void test_deb_verrevcmp_distint_order(void **state)
{
    char *version_a = "0.0";
    char *version_b = "test";
    int revision = 0;

    int ret = deb_verrevcmp(version_a, version_b, revision);
    assert_int_equal(ret, -116);
}

void test_deb_verrevcmp_different_order(void **state)
{
    char *version_a = "0.0";
    char *version_b = "test";
    int revision = 0;

    int ret = deb_verrevcmp(version_a, version_b, revision);
    assert_int_equal(ret, -116);
}

void test_deb_verrevcmp_first_diff(void **state)
{
    char *version_a = "A5";
    char *version_b = "A1";
    int revision = 0;

    int ret = deb_verrevcmp(version_a, version_b, revision);
    assert_int_equal(ret, 4);
}

/* nvd_verrevcmp */
void test_nvd_verrevcmp_version_a_NULL(void **state)
{
    char *version_a = NULL;
    char *version_b = NULL;
    int revision = 0;

    int ret = nvd_verrevcmp(version_a, version_b, revision);
    assert_int_equal(ret, 0);
}

void test_nvd_verrevcmp_version_b_NULL(void **state)
{
    char *version_a = NULL;
    char *version_b = NULL;
    int revision = 0;

    int ret = nvd_verrevcmp(version_a, version_b, revision);
    assert_int_equal(ret, 0);
}

void test_nvd_verrevcmp_revision_NULL(void **state)
{
    char *version_a = NULL;
    char *version_b = NULL;
    int revision = 0;

    int ret = nvd_verrevcmp(version_a, version_b, revision);
    assert_int_equal(ret, 0);
}

void test_nvd_verrevcmp_same_version(void **state)
{
    char *version_a = "0.0.0";
    char *version_b = "0.0.0";
    int revision = 1;

    int ret = nvd_verrevcmp(version_a, version_b, revision);
    assert_int_equal(ret, 0);
}

void test_nvd_verrevcmp_version_a_longer(void **state)
{
    char *version_a = "0.0.0";
    char *version_b = "1.0";
    int revision = 1;

    int ret = nvd_verrevcmp(version_a, version_b, revision);
    assert_int_equal(ret, -1);
}

void test_nvd_verrevcmp_version_b_longer(void **state)
{
    char *version_a = "0.0";
    char *version_b = "1.0.0";
    int revision = 1;

    int ret = nvd_verrevcmp(version_a, version_b, revision);
    assert_int_equal(ret, -1);
}

int main(void) {
    const struct CMUnitTest tests[] = {
        //Tests order
        cmocka_unit_test(test_order_digit),
        cmocka_unit_test(test_order_alpha),
        cmocka_unit_test(test_order_tilde),
        cmocka_unit_test(test_order_other),
        cmocka_unit_test(test_order_zero),
        //Tests pkg_version_relate
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_epoch_NONE, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_epoch_VER_TYPE_unknown, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_epoch_RELATION_unknown, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_epoch_GT, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_epoch_GE, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_epoch_EQ, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_epoch_LE, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_epoch_LT, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_epoch_negative_nvd, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_version_deb_GT, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_version_deb_GT_zero_ending, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_version_deb_GE, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_version_deb_EQ, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_version_deb_LE, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_version_deb_LT, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_version_rpm_GT, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_version_rpm_GT_zero_ending, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_version_rpm_GE, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_version_rpm_EQ, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_version_rpm_LE, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_version_nvd_GE, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_version_nvd_LE, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_version_rpm_LT, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_revision_deb_GT, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_revision_deb_GE, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_revision_deb_EQ, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_revision_deb_LE, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_revision_deb_LT, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_revision_rpm_GT, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_revision_rpm_GE, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_revision_rpm_EQ, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_revision_rpm_LE, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_revision_rpm_LT, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_revision_rpm_tilde, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_revision_rpm_caret_separator, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_revision_deb_null, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_relate_revision_nvd_null, setup_versions, teardown_versions),
        //Tests pkg_version_compare
        cmocka_unit_test_setup_teardown(test_pkg_version_compare_epoch_negative, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_compare_epoch_negative_a_greater, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_compare_epoch_negative_b_greater, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_compare_epoch_same_version, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_compare_a_greater_than_b, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_compare_a_less_than_b, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_compare_version, setup_versions, teardown_versions),
        cmocka_unit_test_setup_teardown(test_pkg_version_compare_revision, setup_versions, teardown_versions),
        //Tests deb_verrevcmp
        cmocka_unit_test(test_deb_verrevcmp_version_a_NULL),
        cmocka_unit_test(test_deb_verrevcmp_version_b_NULL),
        cmocka_unit_test(test_deb_verrevcmp_same_version),
        cmocka_unit_test(test_deb_verrevcmp_text_version),
        cmocka_unit_test(test_deb_verrevcmp_version_a_newer),
        cmocka_unit_test(test_deb_verrevcmp_version_b_newer),
        cmocka_unit_test(test_deb_verrevcmp_different_order),
        cmocka_unit_test(test_deb_verrevcmp_first_diff),
        //Tests nvd_verrevcomp
        cmocka_unit_test(test_nvd_verrevcmp_version_a_NULL),
        cmocka_unit_test(test_nvd_verrevcmp_version_b_NULL),
        cmocka_unit_test(test_nvd_verrevcmp_revision_NULL),
        cmocka_unit_test(test_nvd_verrevcmp_same_version),
        cmocka_unit_test(test_nvd_verrevcmp_version_a_longer),
        cmocka_unit_test(test_nvd_verrevcmp_version_b_longer)
    };
    return cmocka_run_group_tests(tests, NULL, NULL);
}